local cocall = require "cocall"
local constant = require "constant"
local util = require "util"
local game_def = require "game_def"
local table_def = require "table_def"
local table_insert = table.insert
local math_random = math.random

local M = {}
-- local function get_player_store(uid)
--     local ok,ret = R().basesvr({key=uid}):call('.msg_handler','get_curr_control_data',uid)
--     if not ok then
--         errlog(uid, "get_player_store error because ok is nil")
--         return
--     end

--     return {
--         curr_control_status = ret.curr_control_status,
--         curr_control_coins = ret.curr_control_coins,
--         curr_control_weight = ret.curr_control_weight,
--         is_hundred_game = ret.is_hundred_game,
--     }
-- end

--方便各个游戏找问题
function self_print(table_type, ...)
    if table_type == 2004 then 
        dbglog("system_store:print ", ...)
        return 
    end
    dbglog("system_store:print ",table_type, ...)
end


local function get_player_gm_control(uid)
    local ok,ret = R().basesvr({key=uid}):call('.msg_handler','get_player_gm_control',uid)
    if not ok then
        errlog(uid, "get_player_gm_control error because ok is nil")
        return
    end

    return {
        weight = ret.control_weight or 0,
        win_rate = ret.win_rate or 0,
        lose_rate = ret.lose_rate or 0,
        control_coins = ret.curr_control_coins or 0,
        is_hundred_game = ret.is_hundred_game,
    }
end

local function get_player_personal_control(uid)
    local ok,ret = R().basesvr({key=uid}):call('.msg_handler','get_player_personal_control',uid)
    if not ok then
        errlog(uid, "get_player_personal_control error because ok is nil")
        return
    end

    return {
        weight = ret.weight or 0,
        win_rate = ret.win_rate or 0,
        lose_rate = ret.lose_rate or 0,
        control_coins = ret.control_coins or 0,
    }
end

--获取权限值最大的玩家和他的个人库存
-- local function get_max_player_store(player_list,is_hundred_game)
--     local tasks = {}
--     for _,uid in pairs(player_list) do
--         table_insert(tasks,{ f = get_player_store,id = uid,params = {uid}})
--     end
    
--     local ok,results = cocall(5,tasks)
--     if not ok then
--         errlog('failed to cocall',tostring_r(results))
--         return
--     end
--     print_r(results)

--     local power_uid_map_list = {}
--     local max_power
--     for uid,ret in pairs(results) do
--         if ret.curr_control_status > 0 and 
--         ret.curr_control_coins ~= 0 and
--         ret.curr_control_weight > 0 and
--         (is_hundred_game == false or ret.is_hundred_game == 1) then
--             local t = power_uid_map_list[ret.curr_control_weight]
--             if not t then
--                 t = {}
--                 power_uid_map_list[ret.curr_control_weight] = t
--             end
--             table_insert(t,{uid = uid,curr_control_coins = ret.curr_control_coins})
            
--             if not max_power or ret.curr_control_weight > max_power then
--                 max_power = ret.curr_control_weight
--             end
--         end
        
--     end

--     print("rrrrrrrrrr",max_power,tostring_r(power_uid_map_list))
--     if max_power and #power_uid_map_list[max_power] > 0 then
--         local index = math_random(1,#power_uid_map_list[max_power])
--         return power_uid_map_list[max_power][index].uid,power_uid_map_list[max_power][index].curr_control_coins
--     end
-- end

--是否符合GM库存
local function is_match_gm_store(add_coins,warn_coins)
    print("is_match_gm_store=1111",add_coins,warn_coins)
    if not add_coins or not warn_coins then
        return false
    end

    if add_coins < 0 then --输钱时,一定符合
        return true
    end

    local ok,gm_coins = R().exdbsvr(1):call('.gm_coins_mgr','get_gm_coins')
     print("is_match_gm_store=222",add_coins,warn_coins,gm_coins)
    if add_coins > 0 and (gm_coins or 0) > warn_coins then --控制赢钱时gm库存要大于警报值才符合
        return true
    end

    return false
end

-- local function get_player_control_rate(uid,curr_control_coins)
--     if not uid or not curr_control_coins then
--         return 0
--     end

--     local control_rate = 0 
--     local range_control_rate = (global_configs.personal_control or {}).range_control_rate or {}
--     for _,v in pairs(range_control_rate) do
--         if curr_control_coins >= (v.min or 0) and curr_control_coins <= (v.max or 0) then
--             control_rate = v.rate or 0
--         end
--     end
--     print("get_player_control_rate=========",uid,control_rate)
--     local ok,ret = R().basesvr({key=uid}):call('.msg_handler','get_player_control_rate',uid)
--     if ok and ret then
--         if curr_control_coins > 0 and ret.win_rate > 0 then
--             return ret.win_rate or 0
--         end
--         if curr_control_coins < 0 and ret.lose_rate > 0 then
--             return ret.lose_rate or 0
--         end
--     end

--     return control_rate
-- end

--获取权限值最大的玩家GM控制
local function get_max_player_gm_control(player_list, is_hundred_game)
    local gm_tasks = {}
    for _,uid in pairs(player_list) do
        table_insert(gm_tasks,{ f = get_player_gm_control,id = uid,params = {uid}})
    end
    
    local ok,results = cocall(5,gm_tasks)
    if not ok then
        errlog('failed to cocall',tostring_r(results))
        return
    end
    print_r(results)

    local power_uid_map_list = {}
    local max_weight
    for uid,ret in pairs(results) do
        if ret.control_coins ~= 0 and (is_hundred_game == false or ret.is_control_hundred_game == 1) then
            power_uid_map_list[ret.weight] = power_uid_map_list[ret.weight] or {}
            local player_data = {
                uid = uid,
                control_coins = ret.control_coins,
                win_rate = ret.win_rate,
                lose_rate = ret.lose_rate,
            }
            table_insert(power_uid_map_list[ret.weight],player_data)

            if not max_weight or ret.weight > max_weight then
                max_weight = ret.weight
            end
        end
        
    end

    print("rrrrrrrrrr",max_weight,tostring_r(power_uid_map_list))
    if max_weight and #power_uid_map_list[max_weight] > 0 then
        local index = math_random(1,#power_uid_map_list[max_weight])
        local uid = power_uid_map_list[max_weight][index].uid
        local control_coins = power_uid_map_list[max_weight][index].control_coins
        local win_rate = power_uid_map_list[max_weight][index].win_rate
        local lose_rate = power_uid_map_list[max_weight][index].lose_rate
        local control_rate = (control_coins >= 0) and win_rate or lose_rate
        
        return uid,control_coins,control_rate,max_weight
    end
end

--获取权限值最大的玩家个人控制
local function get_max_player_personal_control(player_list)
    local personal_tasks = {}
    for _,uid in pairs(player_list) do
        table_insert(personal_tasks,{ f = get_player_personal_control,id = uid,params = {uid}})
    end
    
    local ok,results = cocall(5,personal_tasks)
    if not ok then
        errlog('failed to cocall',tostring_r(results))
        return
    end
    print_r(results)

    local power_uid_map_list = {}
    local max_weight
    for uid,ret in pairs(results) do
        if ret.control_coins ~= 0 then
            power_uid_map_list[ret.weight] = power_uid_map_list[ret.weight] or {}
            local player_data = {
                uid = uid,control_coins = ret.control_coins,
                win_rate = ret.win_rate,lose_rate = ret.lose_rate
            }
            table_insert(power_uid_map_list[ret.weight],player_data)

            if not max_weight or ret.weight > max_weight then
                max_weight = ret.weight
            end
        end
        
    end

    print("rrrrrrrrrr",max_weight,tostring_r(power_uid_map_list))
    if max_weight and #power_uid_map_list[max_weight] > 0 then
        local index = math_random(1,#power_uid_map_list[max_weight])
        local uid = power_uid_map_list[max_weight][index].uid
        local control_coins = power_uid_map_list[max_weight][index].control_coins
        local win_rate = power_uid_map_list[max_weight][index].win_rate
        local lose_rate = power_uid_map_list[max_weight][index].lose_rate
        local control_rate = (control_coins >= 0) and win_rate or lose_rate
        
        return uid,control_coins,control_rate,max_weight
    end
end

function M.get_personal_system_store_result(table_type,player_list,gm_warn,is_have_robot)
    --dbglog("get_personal_system_store_result00",robot_type,tostring_r(player_list),gm_warn,is_have_robot)
    if player_list and #player_list > 0 then
        local roomdata = global_configs.roomdata[table_type]
        local robot_store = global_configs.robot_store[roomdata.robot_type] or {}
        local base_warn = robot_store.base_min or 0
        local is_hundred_game = roomdata.is_hundred_game

        local ok,succ,system_coins = R().robotmgr(1):call('.msg_handler','get_total_coins',table_type)
        self_print(table_type, "get_personal_system_store_result==============",ok,succ,system_coins,base_warn)
        --先触发GM控制 当前基础库存必须满足不被击穿
        if ok and succ and system_coins > (base_warn or 0) then
            local uid,curr_control_coins,control_rate,weight = get_max_player_gm_control(player_list, is_hundred_game)
            --必须满足GM库存水位线
            local match_gm_store = is_match_gm_store(curr_control_coins,gm_warn)
            self_print(table_type, "get_personal_system_store_result11",uid,curr_control_coins,control_rate,weight)
            if uid and curr_control_coins and control_rate and math_random(1,100) <= control_rate and match_gm_store then
                if curr_control_coins > 0 then
                    return constant.PERSONAL_STORE_WIN,uid,control_rate
                elseif curr_control_coins < 0 then
                    return constant.PERSONAL_STORE_LOSE,uid,control_rate
                end
            end

            --再检查是否可以触发个人控制(非百人类以及捕鱼都不触发)
            if not is_hundred_game and game_def.get_game_type(table_type) ~= table_def.GAME_TYPE_FISHING and #player_list == 1 then --只有一个真实玩家才会触发个控
                local uid,curr_control_coins,control_rate,weight = get_max_player_personal_control(player_list)
                local match_gm_store = is_match_gm_store(curr_control_coins,gm_warn)
                self_print(table_type, "get_personal_system_store_result22",uid,curr_control_coins,control_rate,weight)
                if uid and curr_control_coins and control_rate and math_random(1,100) <= control_rate and match_gm_store then
                    if curr_control_coins > 0 then
                        self_print(table_type, constant.PERSONAL_STORE_WIN,uid,control_rate)
                        return constant.PERSONAL_STORE_WIN,uid,control_rate
                    elseif curr_control_coins < 0 then
                        self_print(table_type, constant.PERSONAL_STORE_LOSE,uid,control_rate)
                        return constant.PERSONAL_STORE_LOSE,uid,control_rate
                    end
                end
            end
        end

    end
    
    --有机器人才触发系统库存控制
    local result = 0
    if is_have_robot then
        local ok,system_result = R().robotmgr(1):call('.msg_handler','check_system_store',table_type)
        self_print(table_type,"get_personal_system_store_result33 robot_type:",robot_type," ok:",ok," system_result:",system_result)
        if not ok then
            errlog("check_system_store fail because ok is nil")
            return result
        end
        return system_result
    end

    return result
end


--gm与个控(水果机用) gm控(捕鱼用)
function M.get_player_personal_control_result(uid, gm_warn, table_type)
    if not uid then
        return 0
    end
    local ok,ret = R().basesvr({key=uid}):call('.msg_handler', 'is_affected',uid)
    self_print("____1_____get_player_personal_control_result____________",uid, ret)
    if not ok or not ret then
        errlog(uid, "get_player_store error because ok is nil")
        return 0
    end
    if table_type and game_def.get_game_type(table_type) ~= table_def.GAME_TYPE_FISHING then 
        if ret.control_type ~= 2 then 
            return 0
        end
    end
    local match_gm_store = is_match_gm_store(ret.control_coins,gm_warn)
    local num = math_random(1,100)
    self_print("____2_____get_player_personal_control_result____________", uid,num,ret.control_rate,match_gm_store  )
    if ret.control_coins and ret.control_rate and num <= ret.control_rate and match_gm_store then
        self_print("____3_____get_player_personal_control_result____________", uid )
        if ret.control_win then
            return constant.PERSONAL_STORE_WIN
        else
            return constant.PERSONAL_STORE_LOSE
        end
    end
    return 0
end


local function check_last_trigger_time(uid,curr_time,interval)
    print("check_last_trigger_time",uid,curr_time,interval)
    local ok,ret = R().basesvr({key=uid}):call('.msg_handler','check_caishen_trigger_time',uid,curr_time,interval)
    if not ok then
        return false
    end
    return ret
end

local function get_vip_cfg(vip_level)
    for _,data in pairs(global_configs.vip) do
        if vip_level == data.level then
            return data
        end
    end

    return {}
end

function M.check_trigger_caishenjiadao(uid,coins,table_type,vip_level)
    local caishenjiadao = global_configs.caishenjiadao
    local vip = global_configs.vip
    if not caishenjiadao.switch then
        return false
    end

   -- print(coins,tostring_r(caishenjiadao))
    if coins < caishenjiadao.tigger_coins then
        return false
    end

    --print("table_type",table_type,vip_level)
    local vip_cfg = get_vip_cfg(vip_level)
    if (caishenjiadao.room_type_rate[table_type] or 0) <= 0 then --玩法场次的基础触发概率为0,就不触发
        return false
    end
    --触发财神概率（百分比） = 当前房间概率  +  VIP加成概率 
    local rate = (caishenjiadao.room_type_rate[table_type] or 0) + (vip_cfg.caishen_base_rate or 0)
    if math_random(1,100) > rate then
        return false
    end

    if check_last_trigger_time(uid,util.get_now_time(),caishenjiadao.interval) then
        return true
    end

    return false
end    

function M.check_caishen_store_result(table_type,uid,coins)
    local caishenjiadao_store = global_configs.caishenjiadao_store
    local base_warn = caishenjiadao_store.base_warn
    local base_goal = caishenjiadao_store.base_goal
    local base_tigger_rate = caishenjiadao_store.base_tigger_rate
    local fee_rate = caishenjiadao_store.fee_rate

    local ok,ret = R().exdbsvr(1):call('.caishen_mgr','check_caishen_store',
    table_type,uid,coins,base_warn,base_goal,base_tigger_rate,fee_rate)
    print("caishen_mgr",ok,ret)
    if not ok then
        errlog("get caishen store failed")
        return false
    end

    print("1111111222222222222")
    return ret

end



M.get_max_player_store = get_max_player_store
M.is_match_gm_store = is_match_gm_store
M.get_player_control_rate = get_player_control_rate

return M